package com.jahentao.patentQuery.service.impl;

import com.jahentao.patentQuery.mapper.*;
import com.jahentao.patentQuery.model.*;
import com.jahentao.patentQuery.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

/**
 * @author jahentao
 * @date 2018/4/13
 * @since 1.0
 */
@Service
public class UserServiceImpl extends BaseServiceImpl  implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleKeyMapper userRoleKeyMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RoleResourceKeyMapper roleResourceKeyMapper;
    @Autowired
    private ResourceMapper resourceMapper;
    @Override
    public User selectByKey(Long key) {
        return userMapper.selectByPrimaryKey(key);
    }

    @Override
    public Integer save(User entity) {
        return userMapper.insert(entity);
    }

    @Override
    public Integer delete(Long key) {
        return userMapper.deleteByPrimaryKey(key);
    }

    @Override
    public Integer updateAll(User entity) {
        return userMapper.updateByPrimaryKey(entity);
    }

    @Override
    public Integer updateNotNull(User entity) {
        return userMapper.updateByPrimaryKeySelective(entity);
    }

    @Override
    public List<User> selectByExample(Object example) {
        return userMapper.selectByExample((UserExample) example);
    }


    ////////////new

    @Override
    public User findByUsername(String username) {
        UserExample userExample = new UserExample();
        userExample.setDistinct(true);
        userExample.createCriteria().andUsernameEqualTo(username);
        List<User> users = userMapper.selectByExample(userExample);
        if (users == null || users.size() == 0) {
            return null;
        } else {
            return users.get(0);
        }
    }
    @Override
    public Set<String> findRoles(String username) {
        User user = findByUsername(username);
        if (user == null || user.getId() == null) {
            return null;
        }

        List<Role> roles = getRolesByUser(user);

        Set<String> rolesStringSet = new HashSet<String>();

        roles.forEach(role -> {
            rolesStringSet.add(role.getRole());
        });

        return rolesStringSet;
    }


    private Consumer<UserRoleKey> addRoleAction;
    /**
     * 获取用户相应的角色
     */
    private List<Role> getRolesByUser(User user) {
        List<Role> roleList = new ArrayList<Role>();

        // 将连接操作留在应用层完成，因为Maaper层修改了很麻烦，发现编写修改Mapper.xml是效率很低的，还经常出错
        // 在应用层处理采用面向对象的思维，很方便，开发效率会高
        UserRoleKeyExample userRoleKeyExample = new UserRoleKeyExample();
        userRoleKeyExample.createCriteria().andUserIdEqualTo(user.getId());
        List<UserRoleKey> userRoleKeys = userRoleKeyMapper.selectByExample(userRoleKeyExample);

        // 懒加载应用在Field变量上
        if (addRoleAction == null) {
            this.addRoleAction = userRoleKey -> {
                RoleExample roleExample = new RoleExample();
                roleExample.createCriteria().andIdEqualTo(userRoleKey.getRoleId());
                List<Role> roles = roleMapper.selectByExample(roleExample);
                if (roles == null || roles.size() == 0) {
                    return;
                }
                roleList.add(roles.get(0));
            };
        }

        user.setRoles(roleList);
        userRoleKeys.forEach(addRoleAction);

        return roleList;
    }

    private Consumer<Role> addPermissonAction;

    @Override
    public Set<String> findPermissions(String username) {
        User user = findByUsername(username);
        if (user == null || user.getId() == null) {
            return null;
        }

        List<Role> roles = getRolesByUser(user);

        Set<String> permissionStringSet = new HashSet<String>();

        // 懒加载
        if (addPermissonAction == null) {
            addPermissonAction = role -> {
                RoleResourceKeyExample roleResourceKeyExample = new RoleResourceKeyExample();
                roleResourceKeyExample.createCriteria().andRoleIdEqualTo(role.getId());
                List<RoleResourceKey> roleResourceKeys = roleResourceKeyMapper.selectByExample(roleResourceKeyExample);

                roleResourceKeys.forEach(roleResourceKey -> {
                    ResourceExample resourceExample = new ResourceExample();
                    resourceExample.createCriteria().andIdEqualTo(roleResourceKey.getResourceId());
                    List<Resource> resources = resourceMapper.selectByExample(resourceExample);

                    resources.forEach(resource -> {
                        permissionStringSet.add(resource.getPermission());
                    });
                });
            };
        }

        roles.forEach(addPermissonAction);

        return permissionStringSet;
    }

    @Override
    public List<User> getRegisteredUser() {
        UserExample userExample = new UserExample();
        userExample.createCriteria().andUtypeEqualTo(String.valueOf(User.UserTypeEnum.USER));
        return userMapper.selectByExample(userExample);
    }

    @Override
    public List<User> getVisitor() {
        UserExample userExample = new UserExample();
        userExample.createCriteria().andUtypeEqualTo(String.valueOf(User.UserTypeEnum.VISITOR));
        return userMapper.selectByExample(userExample);
    }
}
